#ifndef __fbmem_bmp_deconfig__h__
#define __fbmem_bmp_deconfig__h__

#define BMP_SERIVE_ADDR 0x81E00000

struct bmp_info
{
    uint16_t bmp_mark;
    uint32_t bmp_size;
    uint32_t aside;
    uint32_t data_offset;
    uint32_t info_size;
    uint32_t width;
    uint32_t height;
    uint16_t Planes;
    uint16_t bpp;
    uint32_t tar_mode;
    uint32_t image_byte;
    uint32_t level;
    uint32_t vertical;
    uint32_t bit;
};




/*原始BMP图片数据*/
static uint8_t *file_bmp_data;
static uint8_t *image_info_address;

/*解码后的数据*/
uint8_t *decode_data = NULL;

int Sorting_change(uint8_t *bmp, uint32_t width, uint32_t height, uint16_t bmp_numbyte)
{
    int i;
    uint32_t *bit32_p = NULL, *bit32_bmp = NULL;
    uint8_t *false_bit24_p = NULL, *false_bit24_bmp = NULL;
    uint16_t *bit16_p = NULL, *bit16_bmp = NULL;
    // uint8_t r,g,b;
    decode_data = kmalloc(width * height * bmp_numbyte, GFP_KERNEL);
    if (decode_data == NULL)
    {
        printk(KERN_WARNING "LOGO mem bit24_bmp_decode failed\n");
        return 1;
    }

    /*
    *MBP文件第一个数据存储的额是右下角点数据
    *次循环是颠倒顺序，按BMP图片位数颠倒
    */
    if (bmp_numbyte == 2)
    {
        bit16_p = (uint16_t *)decode_data;
        bit16_bmp = (uint16_t *)bmp;
    }
    else if (bmp_numbyte == 3)
    {
        false_bit24_p = (uint8_t *)decode_data;
        false_bit24_bmp = (uint8_t *)bmp;

        /*指向数据尾*/
        false_bit24_bmp += (width * height * bmp_numbyte);
    }
    else if (bmp_numbyte == 4)
    {
        bit32_p = (uint32_t *)decode_data;
        bit32_bmp = (uint32_t *)bmp;
    }

    for (i = 0; i < width * height; i++)
    {
        switch (bmp_numbyte)
        {
        case 1:
            decode_data[i] = bmp[(width * height) - i];
            break;
        case 2:
            bit16_p[i] = bit16_bmp[(width * height) - i];
            break;
        case 3:

            *false_bit24_p++ = *false_bit24_bmp--;
            *false_bit24_p++ = *false_bit24_bmp--;
            *false_bit24_p++ = *false_bit24_bmp--;

            // b = *false_bit24_bmp;
            // false_bit24_bmp--;
            // g = *false_bit24_bmp;
            // false_bit24_bmp--;
            // r = *false_bit24_bmp;
            // false_bit24_bmp--;

            // *false_bit24_p = b;
            // false_bit24_p++;
            // *false_bit24_p = g;
            // false_bit24_p++;
            // *false_bit24_p = r;
            // false_bit24_p++;
            break;
        case 4:
            bit32_p[i] = bit32_bmp[(width * height) - i];
            break;
        default:
            return 1;
        }
    }
    return 0;
}

int bmp_decode(uint32_t *width, uint32_t *height, uint8_t *bpp, uint8_t **data)
{
    // int i;
    // static uint8_t *addr;
    static struct bmp_info bmp_image_info;

    /*将物理地址映射为虚拟地址*/
    image_info_address = ioremap_nocache(BMP_SERIVE_ADDR, sizeof(struct bmp_info));
    if (image_info_address == NULL)
    {
        printk(KERN_WARNING "LOGO mem application failed\n");
        return 1;
    }

    /*开始使用的地址映射，发现数据不对，因该是16位和32位地址对其问题*/
    bmp_image_info.bmp_mark = readw(image_info_address);
    image_info_address += 2;
    bmp_image_info.bmp_size = readl(image_info_address);
    image_info_address += 4;
    bmp_image_info.aside = readl(image_info_address);
    image_info_address += 4;
    bmp_image_info.data_offset = readl(image_info_address);
    image_info_address += 4;
    bmp_image_info.info_size = readl(image_info_address);
    image_info_address += 4;
    bmp_image_info.width = readl(image_info_address);
    image_info_address += 4;
    bmp_image_info.height = readl(image_info_address);
    image_info_address += 4;
    bmp_image_info.Planes = readl(image_info_address);
    image_info_address += 2;
    bmp_image_info.bpp = readl(image_info_address);
    image_info_address += 2;
    bmp_image_info.tar_mode = readl(image_info_address);

    printk(KERN_INFO "BMP file size is %d\n", bmp_image_info.bmp_size);
    printk(KERN_INFO "BMP bpp is %d\n", bmp_image_info.bpp);
    printk(KERN_INFO "BMP data offset is %d\n", bmp_image_info.data_offset);
    printk(KERN_INFO "BMP tar_mode is %d\n", bmp_image_info.tar_mode);

    /*文件合法性判断*/
    if (bmp_image_info.bmp_mark != 0x4D42)
    {
        printk(KERN_WARNING "Logo file is not BMP,%x\n", bmp_image_info.bmp_mark);
        return 1;
    }
    if (bmp_image_info.tar_mode != 0)
    {
        printk(KERN_WARNING "You need to use an uncompressed BMP file,%x\n", bmp_image_info.tar_mode);
        return 1;
    }
    if ((bmp_image_info.bpp != 8) && (bmp_image_info.bpp != 16) && (bmp_image_info.bpp != 24) && (bmp_image_info.bpp != 32))
    {
        printk(KERN_WARNING "Logo file bpp error,%x\n", bmp_image_info.bpp);
        return 1;
    }

    /*取出像素数据*/
    file_bmp_data = ioremap_nocache((BMP_SERIVE_ADDR + bmp_image_info.data_offset), (bmp_image_info.width * bmp_image_info.height) * (bmp_image_info.bpp / 8));
    if (file_bmp_data == NULL)
    {
        printk(KERN_WARNING "LOGO file_bmp_data mem application failed\n");
        return 1;
    }

    if(Sorting_change(file_bmp_data, bmp_image_info.width, bmp_image_info.height, (bmp_image_info.bpp / 8)))
        return 1;

    *bpp = bmp_image_info.bpp;
    *width = bmp_image_info.width;
    *height = bmp_image_info.height;
    *data = decode_data;

    return 0;
}

void ioremap_del(void)
{
    kfree(decode_data);
    iounmap(image_info_address);
    iounmap(file_bmp_data);
}

#endif
